/*
mode by xiaoxiaoyudu
github :https://github.com/xiaoxiaoyudu
qq :1907383069
blbl:两位真实好友
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_system.h"
#include "esp_vfs.h"
#include "esp_spiffs.h"
#include "freertos/event_groups.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "mqtt_client.h"

//#include "chinese.h"
/*wp*/
#include "wificonnet.h"
#include "http.h"
#include "gui.h"
#include "gui_time.h"
#include "gbk.h"
#include "dht11.h"
#include "u2c.h"
#include "adc.h"
#include "button.h"
#include "page.h"
#include "file_server.h"
#include "menu2.h"
TFT_t DEV;
static const char *TAG = "bilibili";
// extern static EventGroupHandle_t s_wifi_event_group;//wifi事件�??
//static EventGroupHandle_t mqtt_event_group;//mqtt事件�??
FontxFile fx16M[2];
FontxFile fx24M[2];
FontxFile fx32M[2];
extern const int CONNECTED_BIT ;
extern const int ESPTOUCH_DONE_BIT ;
extern const int WIFI_SMART;
extern BILIBILI wp_fans;//粉丝结构体
extern struct DATA_WEATHER weather_data[3];
extern xQueueHandle gpio_evt_queue ;
extern xQueueHandle page_evt_queue ;
httpd_handle_t server ;//文件服务句柄
esp_mqtt_client_handle_t client;
typedef struct {
	void (*fun)();
} PAGE;
struct
{   
    uint8_t wifi;
    uint8_t key;
    menu_t *last;
    menu_t *now;
    uint8_t ctrl;
    uint8_t input;
}sys_info;
extern INROOM wp;
PAGE main_page[3]={{page_first},{page_second},{page_three}};

uint16_t *lcd_buff;
static void SPIFFS_Directory(char * path) {
	DIR* dir = opendir(path);
	assert(dir != NULL);
	while (true) {
		struct dirent*pe = readdir(dir);
		if (!pe) break;
		ESP_LOGI(__FUNCTION__,"d_name=%s d_ino=%d d_type=%x", pe->d_name,pe->d_ino, pe->d_type);
	}
	closedir(dir);
}

void All_init()
{
	ESP_LOGI(TAG, "Initializing SPIFFS");
	esp_vfs_spiffs_conf_t conf = {
		.base_path = "/spiffs",
		.partition_label = NULL,
		.max_files = 8,
		.format_if_mount_failed =true
	};
	esp_err_t ret =esp_vfs_spiffs_register(&conf);
	if (ret != ESP_OK) 
	{
		if (ret == ESP_FAIL)
			ESP_LOGE(TAG, "Failed to mount or format filesystem");
		else if (ret == ESP_ERR_NOT_FOUND)
			ESP_LOGE(TAG, "Failed to find SPIFFS partition");
		else
			ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)",esp_err_to_name(ret));
		return;
	}
	size_t total = 0, used = 0;
	ret = esp_spiffs_info(NULL, &total,&used);
	if (ret != ESP_OK)
		ESP_LOGE(TAG,"Failed to get SPIFFS partition information (%s)",esp_err_to_name(ret));
	else
		ESP_LOGI(TAG,"Partition size: total: %d, used: %d", total, used);
	SPIFFS_Directory("/spiffs/");
	InitFontx(fx16M,"/spiffs/ILMH16XB.FNT",""); // 8x16Dot Mincyo
	InitFontx(fx24M,"/spiffs/ILMH24XB.FNT",""); // 12x24Dot Mincyo
	InitFontx(fx32M,"/spiffs/ILMH32XB.FNT",""); // 16x32Dot Mincyo	
	spi_master_init(&DEV, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO, CONFIG_BL_GPIO);
	lcdInit(&DEV, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_OFFSETX, CONFIG_OFFSETY);
	ESP_ERROR_CHECK( nvs_flash_init() );//检�??nvs_flash初�?�化
	button_init();
	adc_init();
	DHT11_init(25);
}

void DHT_task(void *pvParameter)
{
	int t,h;
    while(1) {

		if(!DHT11_read().status)
		{

			t=DHT11_read().temperature;
			h= DHT11_read().humidity;
			if(t>0&&t<70&&h>0&&h<100)
			{
				wp.temp=t;
				wp.hus=h;
			}
			//ESP_LOGI(TAG,"Temperature is %d \n", DHT11_read().temperature);
       		//ESP_LOGI(TAG,"Humidity is %d\n", DHT11_read().humidity);
		}
		vTaskDelay(10000 / portTICK_RATE_MS);
    }
   vTaskDelete(NULL);
}
void HTTP_task(void *pvParameter)
{
	int i=0;
    while(1) 
	{
		i++;
		if(i%5==0)//五分钟
			get_fans();
		if(i%60==0)
		{
			get_weather();
			i=0;
		}
		vTaskDelay(1000*60 / portTICK_RATE_MS);//一分钟
    }
   vTaskDelete(NULL);
}
void ST7789()
{
	page_on();
	ESP_LOGI(TAG,"esp_get_free_heap_size : %d  \n", esp_get_free_heap_size());
}
static int flag=0,menu=0;
void switch_key()
{
	int stat=0;
    sys_info.last=sys_info.now;
    if (sys_info.ctrl)//按键控制链表
    {
        printf("it into switch\n");
        switch (sys_info.key)	
    {
     case KEY_UP://上
     if(sys_info.now->same_last!=NULL)
     {
         sys_info.now=sys_info.now->same_last;
         menu=MENU_RES;
		xQueueSend(page_evt_queue, &menu, 10);
		xQueueReceive( page_evt_queue, &stat, 500 );//5s
		if(stat==MENU_OK)//ok
		xTaskCreate(sys_info.now->funsion, "page", 2048*2, NULL, 10, NULL);
		else
		{
			ESP_LOGI(TAG,"创建失败");
		}
     }
 
        break;
         case KEY_DOWN://下
         printf("it is down\n");
         if(sys_info.now->same_next!=NULL)
         {
            sys_info.now=sys_info.now->same_next;
			menu=MENU_RES;
			xQueueSend(page_evt_queue, &menu, 10);
			xQueueReceive( page_evt_queue, &stat, 500 );//5s
			if(stat==MENU_OK)//ok
			xTaskCreate(sys_info.now->funsion, "page", 2048*2, NULL, 10, NULL);
			else
			{
				ESP_LOGI(TAG,"创建失败");
			}
         }
        
      
        break;
         case KEY_RES:// 左相当于返回
         if(sys_info.now->last!=NULL)
        {
              sys_info.now=sys_info.now->last;
            sys_info.now->funsion();
        }

        break;
         case KEY_ENTER://右相当于确认
     if(sys_info.now->next!=NULL)
        {
            sys_info.now=sys_info.now->next;
             menu=MENU_RES;
			xQueueSend(page_evt_queue, &menu, 10);
			xQueueReceive( page_evt_queue, &stat,500 );//5s
			if(stat==MENU_OK)//ok
			xTaskCreate(sys_info.now->funsion, "page", 2048*2, NULL, 10, NULL);
			else
			{
				ESP_LOGI(TAG,"创建失败");
			}
        }
         
        break;
    
    default:
        break;
    }
        
    }
    else
    {
        printf("dont have button_own");
    }
    
    
}
static void gui_task(void* arg)
{
    static TickType_t startTick, endTick, diffTick;
	uint32_t io_num;
	uint8_t stat;
	BaseType_t press_key = pdFALSE;
	BaseType_t lift_key = pdFALSE;
	while (1) {
		//接收从消息队列发来的消息
		xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY);
		//记录下用户按下按键的时间点
		if (gpio_get_level(io_num) == 0) {
			press_key = pdTRUE;
			startTick = xTaskGetTickCount();
			//如果当前GPIO口的电平已经记录为按下，则开始减去上次按下按键的时间点
		} else if (press_key) {
			
			lift_key = pdTRUE;//记录抬升时间点
			endTick = xTaskGetTickCount();
            diffTick = endTick - startTick;
		}
		//仅仅当按下标志位和按键弹起标志位都为1时候，才执行回调
		if (press_key & lift_key) {
			press_key = pdFALSE;
			lift_key = pdFALSE;
			//如果大于1s则回调长按，否则就短按回调
			if (diffTick > 100) {
				if(!flag)
				{
					ESP_ERROR_CHECK(start_file_server("/spiffs",server));//启动文件系统
					flag=1;
					ESP_LOGI(TAG, "web文件管理开启");
					uint8_t web=MENU_RES;
					xQueueSend(page_evt_queue, &web, NULL);
					xQueueReceive( page_evt_queue, &stat, 500 );//5s
					if(stat==MENU_OK)//ok
					xTaskCreate(page_four, "page_four", 2048*2, NULL, 10, NULL);
					//httpd_stop(server);
				}else
				{
					httpd_stop(server);
					ESP_LOGI(TAG, "web文件管理关闭，为什么关闭不了，我也不知道");
				}
				
			}else {
				ESP_LOGI(TAG, "按键%d短按触发回调",io_num);
				sys_info.key=io_num;
				switch_key();
				
			}
		}
	}

}
menu_t *head;
menu_t *first;
menu_t *wifi_page;
void menu_init()
{
	sys_info.ctrl=1;//取得按键权
    head=NULL;
    head=add_funsion(head,page_first,"clock");//添加头节点
    printf("creat main\n");
    first=set_page(head,0);//主页面
    set_fun(first,page_first,"main");
    add_funsion(first,page_second,"second");
    add_funsion(first,page_three,"three");
    sys_info.now=first;
}
void app_main(void)
{
	All_init();
	ST7789();
	menu_init();
	xTaskCreate(gui_task, "gpio_task_example", 2048*2, NULL, 10, NULL);
	xTaskCreate(&DHT_task, "DHT_task", 2048, NULL, 11, NULL);
	ESP_LOGI(TAG,"esp_get_free_heap_size : %d  \n", esp_get_free_heap_size());
	CLEAN_LCD
	// while(1)
	// {
	// 	show_clock();
	// }
	
	xTaskCreate(sys_info.now->funsion, "page_first", 2048*2, NULL, 10, NULL);
}
